package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.heima.apis.article.IArticleClient;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.tess4j.Tess4jClient;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {
    @Resource
    private WmNewsMapper wmNewsMapper;

    @Resource
    private WmSensitiveMapper wmSensitiveMapper;


    /**
     * 自媒体文章审核
     *
     * @param id 自媒体文章id
     */
    @Async
    @Override
    public void autoScanWmNews(Integer id) throws Exception {
        //1.查询自媒体文章
        WmNews wmNews = wmNewsMapper.selectById(id);
        if (wmNews == null) {
            throw new RuntimeException("WmNewsAutoScanServiceImpl-文章不存在");
        }

        //如果当前状态为提交状态才审核
        if (wmNews.getStatus() == WmNews.Status.SUBMIT.getCode()) {
            //从文本内容中提取文本内容和图片
            Map<String, Object> textAndImg = handleTextAndImages(wmNews);
            String content = (String) textAndImg.get("content");

            //自管理敏感词过滤
            if (!handleSensitiveScan(wmNews, content)) {
                return;
            }

            //2.审核文本内容  阿里云接口
            Boolean isTextScan = handleTextScan(content, wmNews);
            if (!isTextScan) {
                return;
            }



            //3.审核图片  阿里云接口
            boolean isImgScan = handleImageScan((List<String>) textAndImg.get("images"), wmNews);
            if (!isImgScan) {
                return;
            }

        }
        //4.审核成功，保存app端的相关的文章数据
        ResponseResult responseResult = saveAppArticle(wmNews);

        //回填文章id
        wmNews.setArticleId((Long) responseResult.getData());
        updateWmNews(wmNews, (short) 9, "审核成功");

    }

    /**
     * 自管理敏感词过滤
     * @param wmNews
     * @param content
     * @return
     */
    private boolean handleSensitiveScan(WmNews wmNews, String content) {
        //先获取所有的敏感词
        List<WmSensitive> wmSensitives = wmSensitiveMapper.selectList(null);
        List<String> collect = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());
        //生成关键词字典库
        SensitiveWordUtil.initMap(collect);
        //获取匹配的关键词和命中次数
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        if (map.size() > 0) {
            updateWmNews(wmNews, (short) 2, "当前文章中存在违规内容" + map);
            return false;
        }
        return true;
    }

    @Autowired
    private WmChannelMapper wmChannelMapper;

    @Autowired
    private WmUserMapper wmUserMapper;

    @Resource
    private IArticleClient articleClient;

    /**
     * 保存app端的文章数据
     *
     * @param wmNews
     * @return
     */
    private ResponseResult saveAppArticle(WmNews wmNews) {
        ArticleDto dto = new ArticleDto();
        //属性的拷贝
        BeanUtils.copyProperties(wmNews, dto);
        //文章的布局
        dto.setLayout(wmNews.getType());
        //频道名称
        WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
        dto.setChannelName(wmChannel.getName());
        //作者
        dto.setAuthorId(wmNews.getUserId().longValue());
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        if (wmUser != null) {
            dto.setAuthorName(wmUser.getName());
        }

        //设置文章id
        if (wmNews.getArticleId() != null) {
            dto.setId(wmNews.getArticleId());
        }
        //设置创建时间
        dto.setCreatedTime(new Date());

        ResponseResult responseResult = articleClient.saveArticle(dto);
        if (!responseResult.getCode().equals(200)) {
            throw new RuntimeException("WmNewsAutoScanServiceImpl-文章审核，保存app端相关文章数据失败");
        }

        return responseResult;

    }

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private GreenImageScan greenImageScan;

    @Autowired
    private Tess4jClient tess4jClient;

    /**
     * 审核图片
     *
     * @param images
     * @param wmNews
     * @return
     */
    private boolean handleImageScan(List<String> images, WmNews wmNews) throws Exception {
        boolean flag = true;

        //参数检查
        if (images == null || images.size() == 0) {
            return flag;
        }

        //下载图片
        //图片去重
        List<byte[]> imageList = new ArrayList<>();

        List<String> imagesNew = images.stream().distinct().collect(Collectors.toList());
        for (String s : imagesNew) {
            //从minio中下载图片
            byte[] bytes = fileStorageService.downLoadFile(s);
            imageList.add(bytes);

            //图片识别文字审核---begin-----
            BufferedImage imag = ImageIO.read(new ByteArrayInputStream(bytes));
            String doOCR = tess4jClient.doOCR(imag);
            Boolean aBoolean = handleTextScan(doOCR, wmNews);
            if (!aBoolean) {
                return aBoolean;
            }
            //图片识别文字审核---end-----

        }

        //图片审核
        Map map = greenImageScan.imageScan(imageList);
        if (map != null) {
            //审核失败
            if (map.get("suggestion").equals("block")) {
                flag = false;
                updateWmNews(wmNews, (short) 2, "当前文章中存在违规内容");
            }
            //不确定信息,需要人工审核
            if (map.get("suggestion").equals("review")) {
                flag = false;
                updateWmNews(wmNews, (short) 3, "当前文章中存在不确定内容");
            }
        }

        return flag;
    }

    @Autowired
    private GreenTextScan greenTextScan;


    /**
     * 审核纯文本内容
     *
     * @param content
     * @param wmNews
     * @return
     */
    private Boolean handleTextScan(String content, WmNews wmNews) throws Exception {
        boolean flag = true;
        if ((content + wmNews.getTitle()).length() == 0) {
            return flag;
        }

        Map greeTextScan = greenTextScan.greeTextScan(content + "-" + wmNews.getTitle());
        if (greeTextScan != null) {
            if (greeTextScan.get("suggestion").equals("block")) {
                flag = false;
                updateWmNews(wmNews, (short) 2, "当前文章中存在违规内容");
            }

            if (greeTextScan.get("suggestion").equals("review")) {
                flag = false;
                updateWmNews(wmNews, (short) 3, "当前文章中存在不确定内容");
            }
        }

        return flag;
    }

    /**
     * 修改文章的的内容
     *
     * @param wmNews
     * @param status
     * @param reason
     */
    private void updateWmNews(WmNews wmNews, short status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wmNewsMapper.updateById(wmNews);
    }

    /**
     * 从文本内容中提取文本内容和图片
     *
     * @param wmNews
     * @return
     */
    private Map<String, Object> handleTextAndImages(WmNews wmNews) {
        //存放文本内容
        StringBuilder sb = new StringBuilder();
        //存放文本中的图片
        List<String> list = new ArrayList();
        //1.从自媒体文章中提取文本和图片
        String content = wmNews.getContent();
        if (StringUtils.isNotEmpty(content)) {
            List<Map> maps = JSONArray.parseArray(content, Map.class);
            for (Map map : maps) {
                if (map.get("type").equals("text")) {
                    //文本内容
                    sb.append(map.get("value"));
                }

                if (map.get("type").equals("image")) {
                    //图片
                    list.add((String) map.get("value"));
                }
            }
        }

        //提取文章封面的图片
        String images = wmNews.getImages();
        if (StringUtils.isNotEmpty(images)) {
            String[] split = images.split(",");
            list.addAll(Arrays.asList(split));
        }

        //返回数据
        sb.append(wmNews.getTitle());
        Map<String, Object> map = new HashMap<>();
        map.put("content", sb.toString());
        map.put("images", list);

        return map;
    }
}
